{ "cells": [ { "cell_type": "markdown", "id": "continuous-certificate", "metadata": {}, "source": [ "
\n",
" Si c'est votre première visite dans ce TP, lisez attentivement chacun des points détaillé après ce paragraphe.
\n",
" Si vous avez déjà commencer à travailler sur ce TP et que vous souhaiter vous déplacer rapidement dans une partie précise vous pouvez choisir la partie que vous souhaitez rejoindre ci-dessous. N'oubliez pas de réexecuter les case contenant des bibliothèques nécessaire au reste du code.
\n",
" Menu de navigation
\n",
" \n",
"
\n",
" math
\n",
" La technologie jupyter permet d'exécuter du code python par un simple clique sur Executer ci-dessus.
\n",
" Les morceaux de code de cette page sont interprétées case par case. Pour savoir quelle case a été interprétée avant une autre, il suffit de repérer le numéro devant la case.
\n",
" Une fois qu'une case a été interprétée (=exécutée), la page garde en mémoire les variables et fonctions lues
\n",
" La plateforme propose quelques outils de purge de la mémoire : \n",
"
\n",
" Pour ne pas perdre votre travail pensez à le sauvegarder régulièrement. Par défault, la sauvegarde par un clic sur la disquette en haut à gauche de page, ou par le racourci clavier classique ctrl+S
\n",
" est une sauvegarde en local, sur le serveur de jupyter. Vous pouvez et devez très régulièrement sauvegarder votre travail sur votre support personnel de sauvegarde (clef USB, se l'envoyer par mail etc). Ce faisant vous disposerez d'un fichier .ipynb (IPYthon NoteBook) qu'il vous suffira de recharger pour avancer. Après le rechargement assurez vous que les fonctionnalités anciennement developpées et variables utilisées sont bien dans la mémoire de la page (en rééxecutant les cases, ou plus rapidement par Kernel > Restart & Run All.
A NOTER : vous pouvez travailler sur le tp (et tout autre fichier .ipynb) hors connexion en installant une version local du notebook de jupyter. Il faut que votre machine possède un interpreteur de python et que vous soyez connecter à internet.\n", "
pip install jupyterlab
jupyter notebook
pandas
est (probablement) python analysis datas. C'est une bibliothèque de gestion des données a l'aide de dataframe. Commençons par charger cette bibliothèque à l'aide de de l'alias pd
.
Pour illustrer cette partie, considérons deux étudiants Alice et Bob avec des notes en mathématiques, statistique et informatique.
" ] }, { "cell_type": "code", "execution_count": 2, "id": "outside-table", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Alice = {'Math': 15, 'Stat': 18, 'Proba': 8}\n", "Bob = {'Math': 10.5, 'Stat': 9, 'Proba': 10, 'Info': 17}\n" ] } ], "source": [ "Alice={\n", " 'Math':15,\n", " 'Stat':18,\n", " 'Proba':8\n", "}\n", "Bob={\n", " 'Math':10.5,\n", " 'Stat':9,\n", " 'Proba':10,\n", " 'Info':17\n", "}\n", "print(\"Alice =\", Alice)\n", "print(\"Bob =\", Bob)" ] }, { "cell_type": "markdown", "id": "internal-audio", "metadata": {}, "source": [ "Le premier outil que pandas
nous offre est la création de serie
que l'on peut extraire d'un jeu de donnée à l'aide la fonction eponyme.
Affichons cette série.
" ] }, { "cell_type": "code", "execution_count": 4, "id": "nearby-bunny", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Math 15\n", "Stat 18\n", "Proba 8\n", "dtype: int64\n" ] } ], "source": [ "print(serieAlice)" ] }, { "cell_type": "markdown", "id": "dried-mistake", "metadata": {}, "source": [ "On constate que python (et jupyter) affiche les données de Alice en deux colonnes (parfaitement alignées) contenant dans la première le nom des étiquettes des données (le nom des matières) et la seconde la valeur des données (les notes).
\n", "\n", "Vous constaterez que le print
a également préciser le type de la donnée (dtype
qui sont ici des entiers).
Affichez la série de bob
.
Observez que le type des données est différent.
" ] }, { "cell_type": "markdown", "id": "instrumental-sussex", "metadata": {}, "source": [ "il est possible de récupérer d'une par les étiquettes et d'autre par les données. Ce sont les méthodes index
et array
.
Vous observez que ces listes sont des types particuliers de pandas
. Gardez en tête qu'ils se comportent comme des listes classique (vous pouvez les caster en list
si vous le souhaitez) et que vous pouvez appliquer les outils classique sur les listes.
Vous aurez remarqué qu'Alice et Bob n'ont pas le même nombre de note. Il est possible de préciser, au moment de la récupération des notes (données), les matières (étiquettes) qui nous intérèssent (et même dans l'ordre qui nous intérèsse).
" ] }, { "cell_type": "code", "execution_count": 9, "id": "sexual-trace", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Alice\n", "Math 15\n", "Stat 18\n", "Proba 8\n", "dtype: int64\n", "Bob\n", "Math 10.5\n", "Stat 9.0\n", "Proba 10.0\n", "dtype: float64\n" ] } ], "source": [ "serieAlice=pd.Series(Alice, index=['Math', 'Stat', 'Proba'] )\n", "print('Alice')\n", "print(serieAlice)\n", "serieBob=pd.Series(Bob, index=['Math', 'Stat', 'Proba'] )\n", "print('Bob')\n", "print(serieBob)" ] }, { "cell_type": "code", "execution_count": 10, "id": "vietnamese-skill", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Alice\n", "Math 15.0\n", "Stat 18.0\n", "Proba 8.0\n", "Info NaN\n", "INFO NaN\n", "dtype: float64\n", "Bob\n", "Math 10.5\n", "Stat 9.0\n", "Proba 10.0\n", "Info 17.0\n", "INFO NaN\n", "dtype: float64\n" ] } ], "source": [ "serieAlice=pd.Series(Alice, index=['Math', 'Stat', 'Proba', 'Info', 'INFO'] )\n", "print('Alice')\n", "print(serieAlice)\n", "serieBob=pd.Series(Bob, index=['Math', 'Stat', 'Proba', 'Info', 'INFO'] )\n", "print('Bob')\n", "print(serieBob)" ] }, { "cell_type": "markdown", "id": "animated-madison", "metadata": {}, "source": [ "Pas de blague ! NaN
est pour not a number pour préciser que la donnée n'existe pas.
A l'aide d'une boucle for
affichez une par une les notes d'Alice (la dernière variable serieAlice
"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "silent-review",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"15.0 18.0 8.0 nan nan "
]
}
],
"source": [
"for noteAlice in serieAlice.array : \n",
" print(noteAlice, end=' ')"
]
},
{
"cell_type": "markdown",
"id": "blocked-scoop",
"metadata": {},
"source": [
"
La fonction isnan
de la bibliothèque math
permet de tester si une valeur est NaN
. En utilisant cette fonction, reprennez votre code précédent et n'afficher que les notes qui existent.
Ecrire la fonction dataManquantes(serie)
qui renvoie la liste des étiquettes des data manquante dans la série.
Les cadres de données ou plus communement les dataframe sont des séries multidimensionnelles. Considérons l'exemple suivant.
" ] }, { "cell_type": "code", "execution_count": 16, "id": "continent-sweden", "metadata": {}, "outputs": [], "source": [ "Alice={\n", " 'Math':15,\n", " 'Stat':18,\n", " 'Proba':8\n", "}\n", "Bob={\n", " 'Math':10.5,\n", " 'Stat':9,\n", " 'Proba':10,\n", " 'Info':17\n", "}\n", "\n", "CLASSE={\n", " \"Alice\" : Alice, \n", " \"Bob\" : Bob\n", "}" ] }, { "cell_type": "markdown", "id": "otherwise-cylinder", "metadata": {}, "source": [ "La fonction DataFrame
transforme cette donnée un objet (plus structuré) de pandas
.
Comme pour les tableaux à double entrée, on peut récupérer les données (un étudiant) en précisant l'étiquette de cette donnée. L'objet que l'on récupère est une série.
" ] }, { "cell_type": "code", "execution_count": 18, "id": "horizontal-single", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Math 10.5\n", "Stat 9.0\n", "Proba 10.0\n", "Info 17.0\n", "Name: Bob, dtype: float64\n" ] } ], "source": [ "print(Classe['Bob'])" ] }, { "cell_type": "code", "execution_count": 19, "id": "helpful-particle", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Matières : ['Math', 'Stat', 'Proba', 'Info']\n", "Note de Alice : [15.0, 18.0, 8.0, nan]\n", "Note de Bob : [10.5, 9.0, 10.0, 17.0]\n" ] } ], "source": [ "print(\"Matières :\", list(Classe.index))\n", "for etu in Classe : \n", " print(\"Note de\", etu, \":\", list(Classe[etu].array))" ] }, { "cell_type": "markdown", "id": "unauthorized-publicity", "metadata": {}, "source": [ "Voici des notes pour 5 matières pour une classe de 30 étudiants. Proposer un programme transformant ces données en dataframe avec les index qui sont les matières.
" ] }, { "cell_type": "code", "execution_count": 20, "id": "multiple-concern", "metadata": {}, "outputs": [], "source": [ "data = {\n", " 'Note 1': {'Etudiant 1': 11.0, 'Etudiant 2': 5.5, 'Etudiant 3': 8.0, 'Etudiant 4': 8.5, 'Etudiant 5': 15.0, 'Etudiant 6': 18.0, 'Etudiant 7': 7.5, 'Etudiant 8': 15.5, 'Etudiant 9': 17.5, 'Etudiant 10': 13.0, 'Etudiant 11': 9.0, 'Etudiant 12': 19.0, 'Etudiant 13': 15.5, 'Etudiant 14': 7.0, 'Etudiant 15': 15.5, 'Etudiant 16': 17.0, 'Etudiant 17': 19.5, 'Etudiant 18': 17.5, 'Etudiant 19': 4.0, 'Etudiant 20': 20.0, 'Etudiant 21': 2.5, 'Etudiant 22': 0.5, 'Etudiant 23': 0.0, 'Etudiant 24': 5.0, 'Etudiant 25': 7.0, 'Etudiant 26': 15.0, 'Etudiant 27': 18.0, 'Etudiant 28': 11.0, 'Etudiant 29': 8.0, 'Etudiant 30': 1.0}, \n", " 'Note 2': {'Etudiant 1': 4.0, 'Etudiant 2': 7.5, 'Etudiant 3': 5.5, 'Etudiant 4': 2.0, 'Etudiant 5': 8.0, 'Etudiant 6': 8.5, 'Etudiant 7': 7.0, 'Etudiant 8': 0.0, 'Etudiant 9': 3.5, 'Etudiant 10': 8.0, 'Etudiant 11': 9.5, 'Etudiant 12': 20.0, 'Etudiant 13': 18.0, 'Etudiant 14': 12.0, 'Etudiant 15': 0.5, 'Etudiant 16': 18.0, 'Etudiant 17': 3.0, 'Etudiant 18': 16.0, 'Etudiant 19': 2.0, 'Etudiant 20': 12.0, 'Etudiant 21': 7.0, 'Etudiant 22': 2.5, 'Etudiant 23': 2.5, 'Etudiant 24': 6.0, 'Etudiant 25': 18.5, 'Etudiant 26': 3.5, 'Etudiant 27': 3.0, 'Etudiant 28': 18.5, 'Etudiant 29': 15.0, 'Etudiant 30': 10.5}, \n", " 'Note 3': {'Etudiant 1': 14.0, 'Etudiant 2': 10.0, 'Etudiant 3': 17.5, 'Etudiant 4': 15.0, 'Etudiant 5': 0.0, 'Etudiant 6': 17.0, 'Etudiant 7': 1.5, 'Etudiant 8': 7.0, 'Etudiant 9': 20.0, 'Etudiant 10': 16.5, 'Etudiant 11': 2.0, 'Etudiant 12': 11.0, 'Etudiant 13': 14.5, 'Etudiant 14': 7.0, 'Etudiant 15': 2.5, 'Etudiant 16': 19.0, 'Etudiant 17': 4.5, 'Etudiant 18': 5.0, 'Etudiant 19': 19.0, 'Etudiant 20': 20.0, 'Etudiant 21': 2.5, 'Etudiant 22': 2.0, 'Etudiant 23': 6.0, 'Etudiant 24': 15.0, 'Etudiant 25': 17.0, 'Etudiant 26': 9.5, 'Etudiant 27': 2.0, 'Etudiant 28': 15.5, 'Etudiant 29': 0.5, 'Etudiant 30': 1.0}, \n", " 'Note 4': {'Etudiant 1': 5.5, 'Etudiant 2': 12.5, 'Etudiant 3': 6.0, 'Etudiant 4': 16.5, 'Etudiant 5': 9.0, 'Etudiant 6': 3.5, 'Etudiant 7': 19.5, 'Etudiant 8': 18.5, 'Etudiant 9': 2.0, 'Etudiant 10': 7.5, 'Etudiant 11': 9.5, 'Etudiant 12': 8.5, 'Etudiant 13': 7.0, 'Etudiant 14': 11.5, 'Etudiant 15': 15.5, 'Etudiant 16': 13.5, 'Etudiant 17': 18.5, 'Etudiant 18': 13.5, 'Etudiant 19': 4.0, 'Etudiant 20': 12.5, 'Etudiant 21': 15.0, 'Etudiant 22': 19.0, 'Etudiant 23': 6.5, 'Etudiant 24': 16.0, 'Etudiant 25': 10.5, 'Etudiant 26': 19.0, 'Etudiant 27': 3.0, 'Etudiant 28': 7.0, 'Etudiant 29': 19.0, 'Etudiant 30': 15.5}, \n", " 'Note 5': {'Etudiant 1': 6.0, 'Etudiant 2': 12.0, 'Etudiant 3': 1.0, 'Etudiant 4': 10.0, 'Etudiant 5': 20.0, 'Etudiant 6': 10.0, 'Etudiant 7': 8.0, 'Etudiant 8': 12.5, 'Etudiant 9': 6.5, 'Etudiant 10': 11.5, 'Etudiant 11': 13.0, 'Etudiant 12': 8.5, 'Etudiant 13': 11.0, 'Etudiant 14': 10.5, 'Etudiant 15': 13.5, 'Etudiant 16': 13.5, 'Etudiant 17': 2.0, 'Etudiant 18': 18.5, 'Etudiant 19': 2.5, 'Etudiant 20': 0.0, 'Etudiant 21': 19.0, 'Etudiant 22': 14.0, 'Etudiant 23': 0.5, 'Etudiant 24': 4.0, 'Etudiant 25': 0.0, 'Etudiant 26': 15.0, 'Etudiant 27': 10.5, 'Etudiant 28': 19.0, 'Etudiant 29': 5.0, 'Etudiant 30': 13.0}\n", "}" ] }, { "cell_type": "code", "execution_count": 21, "id": "published-minneapolis", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Etudiant 1 Etudiant 2 Etudiant 3 Etudiant 4 Etudiant 5 \\\n", "Note 1 11.0 5.5 8.0 8.5 15.0 \n", "Note 2 4.0 7.5 5.5 2.0 8.0 \n", "Note 3 14.0 10.0 17.5 15.0 0.0 \n", "Note 4 5.5 12.5 6.0 16.5 9.0 \n", "Note 5 6.0 12.0 1.0 10.0 20.0 \n", "\n", " Etudiant 6 Etudiant 7 Etudiant 8 Etudiant 9 Etudiant 10 ... \\\n", "Note 1 18.0 7.5 15.5 17.5 13.0 ... \n", "Note 2 8.5 7.0 0.0 3.5 8.0 ... \n", "Note 3 17.0 1.5 7.0 20.0 16.5 ... \n", "Note 4 3.5 19.5 18.5 2.0 7.5 ... \n", "Note 5 10.0 8.0 12.5 6.5 11.5 ... \n", "\n", " Etudiant 21 Etudiant 22 Etudiant 23 Etudiant 24 Etudiant 25 \\\n", "Note 1 2.5 0.5 0.0 5.0 7.0 \n", "Note 2 7.0 2.5 2.5 6.0 18.5 \n", "Note 3 2.5 2.0 6.0 15.0 17.0 \n", "Note 4 15.0 19.0 6.5 16.0 10.5 \n", "Note 5 19.0 14.0 0.5 4.0 0.0 \n", "\n", " Etudiant 26 Etudiant 27 Etudiant 28 Etudiant 29 Etudiant 30 \n", "Note 1 15.0 18.0 11.0 8.0 1.0 \n", "Note 2 3.5 3.0 18.5 15.0 10.5 \n", "Note 3 9.5 2.0 15.5 0.5 1.0 \n", "Note 4 19.0 3.0 7.0 19.0 15.5 \n", "Note 5 15.0 10.5 19.0 5.0 13.0 \n", "\n", "[5 rows x 30 columns]\n" ] } ], "source": [ "#Solution 1, la méthode 'transpose()' échange les data et les index\n", "df=pd.DataFrame(data).transpose()\n", "print(df)" ] }, { "cell_type": "code", "execution_count": 22, "id": "genetic-conclusion", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Etudiant 1 Etudiant 2 Etudiant 3 Etudiant 4 Etudiant 5 \\\n", "Note 1 11.0 5.5 8.0 8.5 15.0 \n", "Note 2 4.0 7.5 5.5 2.0 8.0 \n", "Note 3 14.0 10.0 17.5 15.0 0.0 \n", "Note 4 5.5 12.5 6.0 16.5 9.0 \n", "Note 5 6.0 12.0 1.0 10.0 20.0 \n", "\n", " Etudiant 6 Etudiant 7 Etudiant 8 Etudiant 9 Etudiant 10 ... \\\n", "Note 1 18.0 7.5 15.5 17.5 13.0 ... \n", "Note 2 8.5 7.0 0.0 3.5 8.0 ... \n", "Note 3 17.0 1.5 7.0 20.0 16.5 ... \n", "Note 4 3.5 19.5 18.5 2.0 7.5 ... \n", "Note 5 10.0 8.0 12.5 6.5 11.5 ... \n", "\n", " Etudiant 21 Etudiant 22 Etudiant 23 Etudiant 24 Etudiant 25 \\\n", "Note 1 2.5 0.5 0.0 5.0 7.0 \n", "Note 2 7.0 2.5 2.5 6.0 18.5 \n", "Note 3 2.5 2.0 6.0 15.0 17.0 \n", "Note 4 15.0 19.0 6.5 16.0 10.5 \n", "Note 5 19.0 14.0 0.5 4.0 0.0 \n", "\n", " Etudiant 26 Etudiant 27 Etudiant 28 Etudiant 29 Etudiant 30 \n", "Note 1 15.0 18.0 11.0 8.0 1.0 \n", "Note 2 3.5 3.0 18.5 15.0 10.5 \n", "Note 3 9.5 2.0 15.5 0.5 1.0 \n", "Note 4 19.0 3.0 7.0 19.0 15.5 \n", "Note 5 15.0 10.5 19.0 5.0 13.0 \n", "\n", "[5 rows x 30 columns]\n" ] } ], "source": [ "#Solution 2 : on crée un data frame à la main.\n", "df=pd.DataFrame(data)\n", "X={}\n", "for etu in df.index : \n", " X[etu]={}\n", " for note in df.columns : X[etu][note]=df[note][etu]\n", "df=pd.DataFrame(X)\n", "print(df)" ] }, { "cell_type": "markdown", "id": "spread-affairs", "metadata": {}, "source": [ "... rien de plus simple ! La fonction read_excel
permet de lire et créer un tableau excel et d'associer les noms des indices et des colonnes en fonction des valeurs précisées. Prenons par exemple, les données parcourSup du département STID, dans le fichier PS_STID.xlsx.\n",
"\n",
"
Dans ce tableur, l'indice Classemment indique si le candidat a confirmé son voeu. Si c'est le cas, la valeur vaut ECF sinon elle vaut ENCF
\n", "\n", "Combien de voeux ont été confirmé ?
" ] }, { "cell_type": "code", "execution_count": 25, "id": "behind-unemployment", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Nombre de voeux confirmés : 1084\n" ] } ], "source": [ "nbETU=len(df)\n", "nbECF=0\n", "for i in df.index : \n", " if(df['Classement'][i]=='ECF') : nbECF+=1\n", "print(\"Nombre de voeux confirmés :\", nbECF)" ] }, { "cell_type": "markdown", "id": "brilliant-vitamin", "metadata": {}, "source": [ "Dans un diagramme circulaire, représenter la répartition des candidats suivant leur département de leur lycée d'origine (attention aux valeur NaN
).